home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac Magazin/MacEasy 19
/
Mac Magazin and MacEasy Magazine CD - Issue 19.iso
/
Wissenschaft & Technik
/
BibTeX ƒ
/
Source code
/
file-io.cp
< prev
next >
Wrap
Text File
|
1996-02-18
|
25KB
|
510 lines
/**************************************************************************
* *
* Product: Bibtex *
* Module: File I/O *
* File: file-io.cp *
* Abstract: The functions in this module are rough equivalents to Unix *
* file I/O functions that Bibtex needs. *
* Exports: *
* CloseFile *
* FPrintF *
* FPutC *
* FPutS *
* GetC *
* OpenInputFile *
* OpenOutputFile *
* UnGetC *
* History: *
* 1.0 11-Jul-95 RJZ. Initial version. *
* *
**************************************************************************/
#include "CBibTeXApp.h"
#include "bibutils.h"
#include "BibTeX.h"
#include "file-io.h"
#include <stdarg.h>
// Local variables:
// Output buffer.
static char gBuffer[kBufferSize];
/*************************************************************************
* *
* Function: CloseFile *
* Purpose: Closes a file. *
* Inputs: descPtr is a pointer to a file description structure for *
* the file to be closed. *
* Outputs: None. *
* Exceptions: Throws an exception if an OS error occurs. *
* Side Effects: Closes a file. *
* Design: In addition to closing the file, this function also *
* flushes the volume that contains the file. IM recommends *
* this. *
* Errors: Displays an error message if an OS error occurs. *
* History: *
* 1.0 10-Jul-95 RJZ. Initial version. *
* *
*************************************************************************/
void CloseFile(FileDescPtr descPtr) {
OSErr err;
if (descPtr->refNum != 0) {
err = ::FSClose(descPtr->refNum);
if (err == noErr)
err = ::FlushVol(NULL, descPtr->spec.vRefNum);
descPtr->refNum = 0;
}
// if (err != noErr) {
// FatalOSErr("Problem closing file %s: %s",
// (char *) descPtr->spec.name + 1, err);
// }
delete descPtr;
}
/**************************************************************************
* *
* Function: FPrintF *
* Purpose: Performs formatted I/O to a file. It is the same as *
* fprintf. *
* Inputs: descPtr is a pointer to a file description structure, and *
* format is a pointer to a format string. Zero or more *
* arguments may follow. *
* Outputs: The number of bytes written. *
* Exceptions: Throws an exception if a write error occurs. *
* Side Effects: Writes to a file. *
* Design: Out of the box, Bibtex uses fprintf to format and print *
* error messages. Here I use vsprintf to format the message *
* and then Macintosh file I/O to write the message. As a *
* result, this function behaves just like fprintf. *
* Errors: Checks for I/O errors as a result of the call to FSWrite. *
* History: *
* 1.0 11-Jul-95 RJZ. Initial version. *
* *
**************************************************************************/
long FPrintF(FileDescPtr descPtr, const char *format, ...) {
va_list args; // variable argument list
long count;
OSErr err;
va_start(args, format);
count = vsprintf(gBuffer, format, args);
va_end(args);
if (count > kBufferSize)
FPrintFStdErr("Wrote past end of buffer in FPrintF!\r");
err = ::FSWrite(descPtr->refNum, &count, gBuffer);
if (err != noErr)
FatalOSErr("Error while writing to %s: %s",
(char *) descPtr->spec.name + 1, err);
return count;
}
/*************************************************************************
* *
* Function: FPrintFStdErr *
* Purpose: This function is the equivalent of calling fprintf with *
* the output directed to stderr. In this case we send the *
* output to the log window. *
* Inputs: The inputs are the same as for printf. *
* Outputs: The function value is the number of characters displayed. *
* Exceptions: None. *
* Side Effects: Displays characters on the screen. *
* Errors: None. *
* History: *
* 1.0 29-Jul-95 RJZ. Initial version. *
* *
*************************************************************************/
long FPrintFStdErr(const char *format, ...) {
va_list args; // variable argument list
long count;
va_start(args, format);
count = vsprintf(gBuffer, format, args);
va_end(args);
CBibtexApp::DisplayInLogWindow(gBuffer, count);
return count;
}
/************************************************************************
* *
* Function: FPutC *
* Purpose: Writes a character to a file. *
* Inputs: mess1 is the character to be written. descPtr points to *
* the file where the character will be written. *
* Outputs: None. *
* Exceptions: Throws an exception if an error occurs. *
* Side Effects: Writes to a file. *
* Design: This function mimics the behavior of the Unix function *
* fputc() except that it doesn't have a return value. *
* Instead, if an error occurs, it throws an exception. *
* Errors: Checks for OS errors from the call to FSWrite. *
* History: *
* 1.0 12-Jul-95 RJZ. Initial version. *
* *
************************************************************************/
void FPutC(const char mess1, FileDescPtr descPtr) {
if(descPtr == 0 ) {
FPutC(mess1);
return;
}
long count;
OSErr err;
count = 1;
#if 1
err = ::FSWrite(descPtr->refNum, &count, &mess1);
#else
// attempt to use async write, but I get illegal instruction problems!
IOParam bib_pb; // must be set up elsewhere
bib_pb.ioVRefNum = descPtr->spec.vRefNum; // as union member field
bib_pb.ioRefNum = descPtr->refNum; // as union member field
bib_pb.ioPosMode = fsAtMark; // from wherever
bib_pb.ioReqCount = 1; // the line size
char printchar = mess1;
bib_pb.ioBuffer = &printchar; // the one character
err = PBWriteAsync((ParamBlockRec*) &bib_pb); // write one char
#endif
if (err != noErr)
FatalOSErr("Error while writing to %s: %s",
(char *) descPtr->spec.name + 1, err);
}
/************************************************************************
* *
* Function: FPutC *
* Purpose: Writes a character to a file. *
* Inputs: mess1 is the character to be written. descPtr points to *
* the file where the character will be written. *
* Outputs: None. *
* Exceptions: Throws an exception if an error occurs. *
* Side Effects: Writes to a file. *
* Design: This function mimics the behavior of the Unix function *
* fputc() except that it doesn't have a return value. *
* Instead, if an error occurs, it throws an exception. *
* Errors: Checks for OS errors from the call to FSWrite. *
* History: *
* 1.0 12-Jul-95 VMD. Initial version. *
* *
************************************************************************/
void FPutC(const char mess1) {
long count = 1;
gBuffer[0] = mess1;
gBuffer[1] = '\0';
CBibtexApp::DisplayInLogWindow(gBuffer, count);
}
/*************************************************************************
* *
* Function: FPutS *
* Purpose: Writes a character string to a file. *
* Inputs: mess1 is the string to be written. descPtr points to the *
* file where the string will be written. *
* Outputs: None. *
* Exceptions: Throws an exception if an OS error occurs. *
* Side Effects: Writes to a file. *
* Design: This function mimics the behavior of the Unix function *
* fputs() except that it doesn't have a return value. *
* Instead, it an error occurs, it throws an exception. *
* Errors: Checks for OS errors from the call to FSWrite. *
* History: *
* 1.0 12-Jul-95 RJZ. Initial version. *
* *
*************************************************************************/
void FPutS(const char *mess1, FileDescPtr descPtr) {
long count;
OSErr err;
count = strlen(mess1);
err = ::FSWrite(descPtr->refNum, &count, mess1);
if (err != noErr)
FatalOSErr("Error while writing to %s: %s",
(char *) descPtr->spec.name + 1, err);
}
/**************************************************************************
* *
* Function: FSeek *
* Purpose: Changes the position of the file mark. *
* Inputs: descPtr is a pointer to the file description structure for *
* the file, offset is how much to change the file mark, and *
* "from" indicates how to do the change. *
* Outputs: Returns any OS error that occurs. *
* Exceptions: None. *
* Side Effects: Moves the file mark. *
* Design: This function is designed to mimic the behavior of the *
* Unix fseek() function. Use from = 0 if the offset is from *
* the start of the file, 1 if the offset is from the current *
* mark, and 2 if the offset is from the end of file. If *
* some other (invalid) value is specified, assume that *
* offset is from current mark. *
* Errors: Returns any OS error that occurs because fseek() returns a *
* non-zero value if an error occurs. *
* History: *
* 1.0 10-Jul-95 RJZ. Initial version. *
* *
**************************************************************************/
OSErr FSeek(FileDescPtr descPtr, long offset, short from) {
OSErr err;
// Translate the meaning of "from" from
// its Unix sense to the Macintosh
// equivalent.
switch (from) {
case 0:
from = fsFromStart;
break;
case 1:
from = fsFromMark;
break;
case 2:
from = fsFromLEOF;
break;
default:
from = fsAtMark;
}
err = ::SetFPos(descPtr->refNum, from, offset);
return err;
}
/**************************************************************************
* *
* Function: GetC *
* Purpose: Reads a character from a file. *
* Inputs: descPtr is a pointer to the file description structure for *
* the file. *
* Outputs: The function value is a character returned in a long. *
* Exceptions: Throws an exception if a read error other than an eof *
* occurs. *
* Side Effects: Advances position in file. *
* Design: This function is designed to work like the Unix getc() *
* function. That's why it has to return the character it *
* reads as a long. Otherwise, there's no way to return EOF. *
* Errors: Posts an alert if an error other that eof occurs. *
* History: *
* 1.0 10-Jul-95 RJZ. Initial version. *
* *
**************************************************************************/
long GetC(FileDescPtr descPtr) {
char c;
long count;
OSErr err;
count = 1;
err = ::FSRead(descPtr->refNum, &count, &c);
if (err != noErr) {
if (err == eofErr)
return EOF;
else
FatalOSErr("Error reading from file %s: %s",
(char *) descPtr->spec.name + 1, err);
}
return (unsigned char) c;
}
/**************************************************************************
* *
* Function: OpenInputFile *
* Purpose: Opens an input file for reading. *
* Inputs: descPtr is a pointer to the FileDesc structure of the file *
* to be opened. *
* Outputs: Stuffs the file reference number into the FileDesc *
* structure. *
* Exceptions: Throws an exception if unable to open the file. *
* Side Effects: Opens a file. *
* Design: Originally this was to be an equivalent to the Unix *
* open(). However, it's hard to produce an exact equivalent *
* to this function on the Macintosh. For example, open() *
* creates a file if it doesn't exist. That's why I didn't *
* give this function a name that was similar to open(). *
* Errors: Displays a message if unable to open the file. *
* History: *
* 1.0 10-Jul-95 Initial version. *
* *
**************************************************************************/
void OpenInputFile(FileDescPtr descPtr) {
OSErr err;
err = ::FSpOpenDF(&descPtr->spec, fsRdPerm, &descPtr->refNum);
if (err != noErr)
FatalOSErr("Problem opening file %s: %s",
(char *) descPtr->spec.name + 1, err);
}
/**************************************************************************
* *
* Function: OpenOutputFile *
* Purpose: Opens an output file for writing. *
* Inputs: descPtr is a pointer to the FileDesc structure of the file *
* to be opened. *
* Outputs: Stuffs the file reference number into the FileDesc *
* structure. *
* Exceptions: Throws an exception if unable to open the file. *
* Side Effects: Opens a file. *
* Design: Originally this was to be an equivalent to the Unix *
* open(). However, it's hard to produce an exact equivalent *
* to this function on the Macintosh. For example, open() *
* creates a file if it doesn't exist. That's why I didn't *
* give this function a name that was similar to open(). *
* Errors: Displays a message if unable to open the file. *
* History: *
* 1.0 10-Jul-95 Initial version. *
* *
**************************************************************************/
void OpenOutputFile(FileDescPtr descPtr) {
OSErr err;
err = ::FSpOpenDF(&descPtr->spec, fsWrPerm, &descPtr->refNum);
if (err != noErr)
FatalOSErr("Problem opening file %s: %s",
(char *) descPtr->spec.name + 1, err);
}
/**************************************************************************
* *
* Function: UnGetC *
* Purpose: Puts back a character that was just read. *
* Inputs: ch is the character just read and descPtr is a pointer to *
* the file description structure. *
* Outputs: noErr if successful, EOF if unsuccessful or if ch is EOF. *
* Exceptions: None. *
* Side Effects: Moves the file mark. *
* Design: This works like the Unix function ungetc(). Note that *
* this function will not work for the idx file since the *
* input for that file is buffered. If it becomes necessary *
* to use UnGetC() on the idx file in the future, it *
* will be necessary to stop using buffered input for the idx *
* file or maybe it will be necessary to create a special *
* version of this function for the idx file. *
* Errors: None. *
* History: *
* 1.0 10-Jul-95 RJZ. Initial version. *
* *
**************************************************************************/
int UnGetC(int ch, FileDescPtr descPtr) {
OSErr err;
if (ch != EOF) {
err = ::SetFPos(descPtr->refNum, fsFromMark, -1L);
if (err == noErr)
return noErr;
else
return EOF;
} else
return EOF;
}
boolean FEof(FileDescPtr descPtr) {
long end;
GetEOF(descPtr->refNum, &end);
long curr;
GetFPos(descPtr->refNum, &curr);
return (end == curr);
}
// not static because it needs to be reset each run.
FileDescPtr myBufferedFile;
long GetBibtexCharacter(FileDescPtr descPtr) {
static short bufferPos; // next char to come out of readBuffer
long count; // number of characters to read
OSErr err; // error code
static char readBuffer[kReadBufferSize];
extern FileDescPtr myBufferedFile;
static short myFileEnd;
static long myFilePos;
if(myBufferedFile != descPtr) {
// move pos in old file
if(myBufferedFile)
SetFPos(myBufferedFile->refNum,fsFromStart, myFilePos);
// do new file
myBufferedFile = descPtr;
bufferPos = 0;
myFileEnd = -1;
GetFPos(myBufferedFile->refNum, &myFilePos);
}
if(bufferPos == myFileEnd){
// now we really are at the end
long end;
GetEOF(myBufferedFile->refNum, &end);
SetFPos(myBufferedFile->refNum, fsFromStart, end);
return EOF;
}
if(bufferPos % kReadBufferSize == 0) {
count = kReadBufferSize;
err = ::FSRead(descPtr->refNum, &count, readBuffer);
if (err != noErr) {
if(err == eofErr) {
myFileEnd = count;
// pretend we're not at the end yet
SetFPos(myBufferedFile->refNum, fsFromLEOF, -2);
} else {
FatalOSErr("Error while reading %s: %s", (char*) myBufferedFile->spec.name, err);
}
}
bufferPos = 0;
}
myFilePos++;
return readBuffer[bufferPos++];
}
#define EOL 13 // line delimiter is CR (ASCII 13)
/*
ReadLine reads a line of text from the file represented by pbp.
It returns -1 if the file is not delimited, or a file manager
result code (i.e. eofErr.) It places the null terminated string
in the buffer pointed to by lineBuf.
*/
/*
IOParam bib_pb; // must be set up elsewhere
extern char* buffer;
void ReadLine(FileDescPtr descPtr) // fixed:, char *lineBuf, const int size)
{
extern long last; // BibTeX uses this to keep track of how much was read
bib_pb.ioVRefNum = descPtr->spec.vRefNum; // as union member field
bib_pb.ioRefNum = descPtr->refNum; // as union member field
OSErr rc = PBReadSync((ParamBlockRec*) &bib_pb); // read one line
last = bib_pb.ioActCount;
if (rc==eofErr && last==0){
return; // end of file reached
}
if ((rc==noErr) || (rc==eofErr)) {
if (last==bufsize) {
short in = buffer[last-1];
// skip past eoln if buffer full
while (in != EOF && in != EOL )
in = GetC(descPtr);
return; // not a delimited file
}
if (buffer[last-1] == EOL) // last line has no EOL
last--;
}
}
*/
// for speed in the crucial readline routine, we set these up once only
/* These would have to be put somewhere if we used the above routine
extern IOParam bib_pb;
bib_pb.ioPosMode = fsAtMark | 0x80 | (256*13); // just read a line; EOL = 13
bib_pb.ioReqCount = bufsize; // max line size
bib_pb.ioBuffer = buffer; // transfer to this address
*/